package luke4fun.wheresmymoney.service.async;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import luke4fun.wheresmymoney.adapter.list.impl.MonthAccAdapter;
import luke4fun.wheresmymoney.bean.AccBean;
import luke4fun.wheresmymoney.bean.AccDtlBean;
import luke4fun.wheresmymoney.bean.DayAccBean;
import luke4fun.wheresmymoney.db.AccDBHelper;
import luke4fun.wheresmymoney.db.DBConstants;

public class MonthAsyncAccTask extends AsyncTask<Integer, String, List<DayAccBean>> {

	private AccDBHelper dbHelper;
	private SQLiteDatabase db;
	private MonthAccAdapter adapter;
	private long dateInMillis;
	
	public MonthAsyncAccTask(Context context, MonthAccAdapter adapter, long dateInMillis) {
		dbHelper = new AccDBHelper(context);
		this.adapter = adapter; 
		this.dateInMillis = dateInMillis;
	}

	@Override
	protected List<DayAccBean> doInBackground(Integer... params) {
		List<DayAccBean> beanList = new ArrayList<DayAccBean>();
		
		Calendar c1 = Calendar.getInstance();
		c1.clear();
		c1.setTimeInMillis(dateInMillis);
		int year = c1.get(Calendar.YEAR);
		int month = c1.get(Calendar.MONTH);
		
		c1.clear();
		c1.set(year, month, 1);
		
		Calendar c2 = Calendar.getInstance();
		c2.clear();
		c2.set(year, month+1, 1);
		
		db = dbHelper.getReadableDatabase();
		Cursor cursor = db.rawQuery("SELECT * FROM (SELECT SUM(price) as price, datatime as datatime FROM " + DBConstants.V_RECORD
				+ " where pid = -1 GROUP BY datatime HAVING datatime >= ? AND datatime < ? ORDER BY datatime DESC) t1"
				+ " INNER JOIN " + DBConstants.V_RECORD + " t2 ON t1.datatime=t2.datatime", 
				new String[] {c1.getTimeInMillis() + "", c2.getTimeInMillis() + ""});

		Map<Long, DayAccBean> map = new LinkedHashMap<Long, DayAccBean>();
		while (cursor.moveToNext()) {
			DayAccBean bean;
			AccBean acc = null;
			
			Long millis		= cursor.getLong(cursor.getColumnIndex(DBConstants.RECORD_DATATIME));
			Long id 		= cursor.getLong(cursor.getColumnIndex(DBConstants.RECORD_ID));
			Long pid 		= cursor.getLong(cursor.getColumnIndex(DBConstants.RECORD_PID));
			String item 	= cursor.getString(cursor.getColumnIndex(DBConstants.RECORD_ITEM));
			String category = cursor.getString(cursor.getColumnIndex(DBConstants.RECORD_CATEGORY));
			Integer price = null;
			
			int index = cursor.getColumnIndex(DBConstants.RECORD_PRICE);
			if (!cursor.isNull(index)) {
				price = cursor.getInt(cursor.getColumnIndex(DBConstants.RECORD_PRICE));
			}
			
			// each day, by date in milliseconds
			if (map.containsKey(millis)) {
				bean = map.get(millis);
				acc = bean.getAccMap().get(category);
			} else {
				bean = new DayAccBean();
				bean.setExpenseDate(new Date(millis));
				bean.setPrice(cursor.getInt(0));
			}
			
			// detail
			if (acc == null) {
				acc = new AccBean();
				acc.setCategory(category);
			}

			AccDtlBean dtlBean = new AccDtlBean();
			dtlBean.setId(id);
			dtlBean.setPid(pid);
			dtlBean.setItem(item);
			dtlBean.setPrice(price);
			if (pid == -1) {
				acc.putDtl(id, dtlBean);
				acc.setSum(acc.getSum() + price);
			}
			else {
				acc.getDtl(pid).getInfoList().add(dtlBean);
			}
			
			// put into acc map by category
			bean.getAccMap().put(category, acc);
			// put day info into month map
			map.put(millis, bean);
		}
		
		db.close();
		dbHelper.close();
		beanList.addAll(map.values());
		return beanList;
	}

	@Override
	protected void onPostExecute(List<DayAccBean> result) {
		adapter.updateList(result);
	}
}
